using System;
using NHibernate;
using Rubikev.Common.Data;
using ISession = NHibernate.ISession;

namespace Rubikev.NHibernate
{
   /// <summary>
   /// Adapter for an NHibernate ISession to a core ISession
   /// </summary>
   public class SessionAdapter : Common.Data.ISession, IDisposable
   {
      public SessionAdapter(ISession nHibernateSession)
      {
         NHibernateSession = nHibernateSession;
      }

      /// <summary>
      /// The adapted NHibernate session
      /// </summary>
      public ISession NHibernateSession { get; private set; }

      /// <summary>
      /// The NHibernate session should already be open, so do nothing
      /// </summary>
      public void Open()
      {
      }

      /// <summary>
      /// Closes the session
      /// </summary>
      public void Close()
      {
         if (!NHibernateSession.IsOpen) return;

         NHibernateSession.Close();
      }

      /// <summary>
      /// Begins a transaction
      /// </summary>
      public void BeginTransaction()
      {
         NHibernateSession.BeginTransaction();
      }

      /// <summary>
      /// Commits a transaction
      /// </summary>
      public void CommitTransaction()
      {
         try
         {
            NHibernateSession.Transaction.Commit();
         }
         catch(PropertyValueException ex)
         {
            RollbackTransaction();
            throw new InvalidEntityException(ex.Message, ex);
         }
         catch
         {
            RollbackTransaction();
            throw;
         }
      }

      /// <summary>
      /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
      /// </summary>
      /// <filterpriority>2</filterpriority>
      public void Dispose()
      {
         NHibernateSession.Dispose();
      }

      private void RollbackTransaction()
      {
         try
         {
            NHibernateSession.Transaction.Rollback();
         }
         finally
         {
            NHibernateSession.Close();
         }
      }
   }
}